package com.vshop.platform.system.crud.dao;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.vshop.platform.system.domain.entity.SysRole;
import com.vshop.platform.system.domain.entity.SysRoleDept;
import com.vshop.platform.system.crud.mapper.SysRoleDeptMapper;
import com.vshop.platform.system.domain.param.SysRoleParam;
import org.springframework.stereotype.Repository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static com.mybatisflex.core.query.QueryMethods.select;
import static com.vshop.platform.system.domain.entity.table.SysDeptTableDef.SysDeptTable;
import static com.vshop.platform.system.domain.entity.table.SysRoleDeptTableDef.SysRoleDeptTable;
import static com.vshop.platform.system.domain.entity.table.SysRoleTableDef.SysRoleTable;


/**
 * 角色和部门关联表 服务层实现。
 *
 * @author vshop
 * @since 2024-11-18
 */
@RequiredArgsConstructor
@Slf4j
@Repository
public class SysRoleDeptDao extends ServiceImpl<SysRoleDeptMapper, SysRoleDept> {

    /**
     * 根据角色ID查询部门树信息(已分配)
     *
     * @param roleId 角色ID
     * @return 选中部门列表
     */
    public List<Long> listAllocatedDeptIdByRoleId(Long roleId) {
        SysRole role = this.queryChain()
                .from(SysRoleTable)
                .where(SysRoleTable.RoleId.eq(roleId))
                .oneAs(SysRole.class);

        /*select d.dept_id
        from sys_dept d
        left join sys_role_dept rd on d.dept_id = rd.dept_id
        where rd.role_id = #{roleId}
            <if test="deptCheckStrictly">
            and d.dept_id not in (select d.parent_id from sys_dept d inner join sys_role_dept rd on d.dept_id = rd.dept_id and rd.role_id = #{roleId})
            </if>
        order by d.parent_id, d.order_num*/
        QueryWrapper queryWrapper = QueryWrapper.create()
                .select(SysDeptTable.DeptId)
                .from(SysDeptTable.as("d"))
                .leftJoin(SysRoleDeptTable).as("rd").on(SysRoleDeptTable.DeptId.eq(SysDeptTable.DeptId))
                .where(SysRoleDeptTable.RoleId.eq(roleId));

        //部门树选择项是否关联显示
        if (ObjectUtil.isNotNull(role.getDeptCheckStrictly()) && role.getDeptCheckStrictly().equals(true)) {
            queryWrapper.and(SysDeptTable.DeptId.notIn(
                    select(SysDeptTable.ParentId).from(SysDeptTable)
                            .innerJoin(SysRoleDeptTable).on(
                                    SysRoleDeptTable.DeptId.eq(SysDeptTable.DeptId))
                            .and(SysRoleDeptTable.RoleId.eq(roleId))
            ));
        }
        queryWrapper.orderBy(SysDeptTable.Ancestors.asc())
                .orderBy(SysDeptTable.ParentId.asc())
                .orderBy(SysDeptTable.SortNum.asc());
        return this.listAs(queryWrapper, Long.class);
    }


    /**
     * 新增角色部门信息(数据权限)
     *
     * @param param 角色对象
     */
    public boolean saveRoleDept(SysRoleParam param) {
        boolean inserted = true;
        // 新增角色与部门（数据权限）管理
        List<SysRoleDept> list = new ArrayList<>();
        Optional.ofNullable(param.getDeptIds()).orElse(List.of())
                .forEach(deptId -> {
                    SysRoleDept rd = new SysRoleDept();
                    rd.setRoleId(param.getRoleId());
                    rd.setDeptId(deptId);
                    list.add(rd);
                });
        if (CollUtil.isNotEmpty(list)) {
            inserted = this.saveBatch(list);
        }
        return inserted;
    }


    /**
     * 通过角色ID删除角色和部门关联
     * delete from sys_role_dept where role_id=#{roleId}
     *
     * @param roleId 角色ID
     * @return 结果:true 删除成功，false 删除失败
     */
    public boolean removeRoleDeptByRoleId(Long roleId) {
        QueryWrapper queryWrapper = query()
                .where(SysRoleDeptTable.RoleId.eq(roleId));
        return this.remove(queryWrapper);
    }

    /**
     * 批量删除角色部门关联信息
     * delete from sys_role_dept where role_id in
     *
     * @param roleIds 需要删除的数据ID
     * @return 结果:true 删除成功，false 删除失败。
     */
    public boolean removeRoleDeptByRoleIds(List<Long> roleIds) {
        QueryWrapper queryWrapper = QueryWrapper.create()
                .from(SysRoleDeptTable)
                .where(SysRoleDeptTable.RoleId.in(roleIds));
        return this.remove(queryWrapper);
    }
}
